package com.example.springboot_demo.demos.web.websocket_work.Websocket;

import com.example.springboot_demo.demos.web.book_work.Exception.LibraryException;
import com.example.springboot_demo.demos.web.websocket_work.Mapper.MessageMapper;
import com.example.springboot_demo.demos.web.websocket_work.Pojo.MessageData;
import com.example.springboot_demo.demos.web.websocket_work.Service.MessageBroadcaster;
import com.example.springboot_demo.demos.web.websocket_work.Service.MessageRankService;
import com.example.springboot_demo.demos.web.websocket_work.Service.OnlineUserService;
import com.example.springboot_demo.demos.web.websocket_work.Util.SpringContextHolder;
import com.example.springboot_demo.demos.web.websocket_work.vo.MessageDataVo;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.ConcurrentHashMap;

@Component
@ServerEndpoint("/chat/{chatName}/{senderName}") // 路径参数替代URI解析
public class WebSocketServer {
    //存储聊天室
    public static final ConcurrentHashMap<String, ConcurrentHashMap<String, Session>> chatSessionMap = new ConcurrentHashMap<>();

    //用户名
    public static String key;

    //注入mapper接口
    private static final MessageMapper messageMapper = SpringContextHolder.getBean(MessageMapper.class);


    //转换数据
    public static  final ObjectMapper mapper = new ObjectMapper();
    //注入服务

    /**
     * 用户管理
     */
    private static final OnlineUserService onlineUserService = SpringContextHolder.getBean(OnlineUserService.class);
    /**
     * 统计用户消息数量
     */
    private static final MessageRankService messageRankService = SpringContextHolder.getBean(MessageRankService.class);
    /**
     * 发送广播
     */
    private static final MessageBroadcaster messageBroadcaster = SpringContextHolder.getBean(MessageBroadcaster.class);
    /**
     * 连接时触发
     * @param session
     * @param key
     * @param name
     */

    @OnOpen
    public void onOpen(Session session, @PathParam("chatName") String key ,@PathParam("senderName") String name) {

        System.out.println("连接id：" + session.getId());
        try {
            String decodedKey = URLDecoder.decode(key, "UTF-8");
            String decodedName = URLDecoder.decode(name, "UTF-8");
            chatSessionMap.computeIfAbsent(decodedKey, k -> new ConcurrentHashMap<>())
                        .put(session.getId(), session);


            System.out.println(decodedName + "加入聊天室");

            //当用户加入聊天室后，把当前用户存储到redis在线用户列表中
            onlineUserService.userLogin(decodedName);
            onlineUserService.storeSession(decodedName,session);


            //判断当前聊天室是否有记录, 如果有则查询数据并发送
            if (messageMapper.selectChat(key) > 0){
                List<MessageDataVo> messageDataVo = messageMapper.selectChatByKey(key);
                for (MessageDataVo dataVo : messageDataVo) {
                    dataVo.setType("history");
                }
                mapper.registerModule(new JavaTimeModule());
                // 禁用时间戳格式，强制使用字符串格式
                mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
                // 设置日期格式和时区（可选）
                mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
                mapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));
                //把数据发送给前端
                String json = mapper.writeValueAsString(messageDataVo);
                session.getBasicRemote().sendText(json);

            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 接受消息
     * @param message
     * @param session
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        System.out.println("接受消息" + message);

        //打印用户在线情况
        System.out.println("用户在线情况:" + onlineUserService.getOnlineUsers());

        try {
            ObjectMapper mapper = new ObjectMapper();
            MessageData messageData = mapper.readValue(message, MessageData.class);

            if (chatSessionMap.containsKey(messageData.getChatName())) {

                if (messageData.getType().equals("message")){
                    /**
                     *  判断该用户在规定时间内，发送的信息是否超过30条
                     */
                    if (messageRankService.checkRateLimit(messageData.getSenderName())){
                        messageMapper.insert(messageData);
                        //如果为发送的新消息则增加用户消息计数
                        messageRankService.incrementMessageCount(messageData.getSenderName());

                        //打印用户目前发送信息的排行
                        System.out.println("排序：" + messageRankService.getTopUsers().iterator().next().getValue());
                        System.out.println("数据大小：" + messageRankService.getTopUsers().iterator().next().getScore());
                    }else {
                        MessageData mag = new MessageData();
                        mag.setType("error");
                        mag.setSenderName(messageData.getSenderName());
                        mag.setContent("用户" + mag.getSenderName() + "发送消息过多请稍后重试！");
                        //获取用户当前的会话id，给指定用户发送信息
                        String sessionById = onlineUserService.findSessionById(mag.getSenderName());
                        Session userSession = chatSessionMap.get(messageData.getChatName()).get(sessionById);
                        userSession.getBasicRemote().sendText(mapper.writeValueAsString(mag));
                        return;
                    }
                }

                //发送广播
                key = messageData.getChatName();
                messageBroadcaster.broadcast(message);


                //发送信息
//                ConcurrentHashMap<String, Session> group = chatSessionMap.get(messageData.getChatName());
//                group.values().forEach(s -> {
//                    try {
//                        s.getBasicRemote().sendText(message);
//                    } catch (IOException e) {
//                        e.printStackTrace();
//                    }
//                });
            }else {
                throw new LibraryException("当前没有该聊天室，请检查是否已经断连或聊天室为空");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    @OnClose
    public void onClose(Session session, @PathParam("chatName") String key,@PathParam("senderName") String name) {
        try {
            String decodedKey = URLDecoder.decode(key, "UTF-8");
            String decodedName = URLDecoder.decode(name, "UTF-8");


            if (chatSessionMap.containsKey(decodedKey)) {
                chatSessionMap.get(decodedKey).remove(session.getId());
                if (chatSessionMap.get(decodedKey).isEmpty()) {
                    chatSessionMap.remove(decodedKey);
                }
            }else {
                throw new LibraryException("当前没有该聊天室,无法断开连接");
            }


            //当用户断开连接后删除对应id
            onlineUserService.userLogout(decodedName);
            onlineUserService.removeSession(decodedName);
            //发送广播
            Set<String> users = onlineUserService.getOnlineUsers();

            System.out.println("目前在线的会话：" + String.join(",",users));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}